﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Data.SqlClient;

namespace TestBench
{
    public partial class ExperimentForm : Form
    {
        public ExperimentForm()
        {
            InitializeComponent();
            //InitDictionaries();
            InitResultTable();
        }

        Dictionary<string, byte> RPOSDic = new Dictionary<string, byte>();
        Dictionary<string, byte> GRTypeDic = new Dictionary<string, byte>();
        Dictionary<string, byte> SubTypeDic = new Dictionary<string, byte>();
        Dictionary<string, short> WordDic = new Dictionary<string, short>();
        DataTable _resultTable;

        private void InitDictionaries()
        {
            using (DepBank_DBDataContext context = new DepBank_DBDataContext())
            {
                RPOSDic.Clear();
                GRTypeDic.Clear();
                WordDic.Clear();
                SubTypeDic.Clear();
                var varRPOSSet = from r in context.TBL_RPOs select r;
                foreach (var rpos in varRPOSSet)
                {
                    RPOSDic.Add(rpos.RPOS.Trim(), rpos.RPOSID);
                }

                var varGRTypeSet = from gr in context.TBL_GRTypes select gr;
                foreach (var grval in varGRTypeSet)
                {
                    GRTypeDic.Add(grval.GRType.Trim(), grval.GRTypeID);

                }

                var wordset = from w in context.TBL_WordDics select w;
                foreach (var word in wordset)
                {
                    string key = word.Lema + "_" + word.POS_ID + "_" + word.Word;
                    WordDic.Add(key, word.WordID);
                }

                var subTypeSet = from s in context.TBL_SubTypes select s;
                foreach (var subType in subTypeSet)
                {
                    SubTypeDic.Add(subType.SubType, subType.SubTypeID);
                }
            }
        }
        private void InitResultTable()
        {
            _resultTable = new DataTable();
            #region Create Column
            _resultTable.Columns.Add("EvaluationSetType", typeof(char));
            _resultTable.Columns.Add("SentenceID", typeof(short));
            _resultTable.Columns.Add("GRType", typeof(string));
            _resultTable.Columns.Add("H_Word", typeof(string));
            _resultTable.Columns.Add("H_RPOS", typeof(string));
            _resultTable.Columns.Add("H_Location", typeof(int));
            _resultTable.Columns.Add("D_Word", typeof(string));
            _resultTable.Columns.Add("D_RPOS", typeof(string));
            _resultTable.Columns.Add("D_Location", typeof(int));
            _resultTable.Columns.Add("SubType", typeof(string));
            _resultTable.Columns.Add("InitGR", typeof(string));
            _resultTable.Columns.Add("ParseID", typeof(int));
            _resultTable.Columns.Add("Rank", typeof(int));
            _resultTable.Columns.Add("Score", typeof(float));
            #endregion
        }
        private void btnTest1_Click(object sender, EventArgs ea)
        {
            char evaluationType = 'd';

            using (DepBank_DBDataContext context = new DepBank_DBDataContext())
            {

                int[] sentenceIDs = (from sentence in context.TBL_GoldStandard_GRs where sentence.EvaluationSetType == evaluationType select sentence.SentenceID.Value).Distinct().ToArray();
                foreach (int senID in sentenceIDs)
                {
                    var raspParses = from p in context.TBL_RASP_GRs where p.EvaluationSetType == evaluationType && p.SentenceID == senID select p;
                    int[] parseIDs = (from p in raspParses select p.ParseID.Value).Distinct().ToArray();

                    List<ScoreSet> parseScoreSet = new List<ScoreSet>();

                    parseScoreSet.Add(new ScoreSet { ParseID = 1, Score = 100 });
                    //    for(int parseID=1;parseID<parseIDs.Length && parseID<3;parseID++)
                    //{
                    //    var grSet = from gr in raspParses where gr.ParseID == parseID select gr;
                    //    int grCount = grSet.Count();

                    //    int? joinSet = (from e in grSet join m in context.TBL_Exp_Model_As on new { gr = e.GRTypeID.Value, h = e.H_Word_DicID.Value, d = e.D_Word_DicID.Value } equals new { gr = m.GRType.Value, h = m.H_Lema_ID.Value, d = m.D_Lema_ID.Value }  select m.NumCount).Sum();
                    //    float score = 0;
                    //    if (joinSet.HasValue)
                    //    {
                    //        score = (float)joinSet.Value / grCount;
                    //    }
                    //    parseScoreSet.Add(new ScoreSet { Score = score, ParseID = parseID });
                    //    }

                    var rankSet = (from r in parseScoreSet orderby r.Score descending select r).Take(1);


                    int rankOrder = 1;
                    foreach (var rank in rankSet)
                    {
                        var currentParseSet = from p in raspParses where p.ParseID == rank.ParseID select p;
                        SaveParse(currentParseSet, evaluationType, rankOrder, rank.Score);
                        rankOrder++;
                    }

                    if (_resultTable.Rows.Count > 20000)
                    {
                        WriteDB(_resultTable);
                        _resultTable.Rows.Clear();
                    }
                }

                if (_resultTable.Rows.Count > 0)
                {
                    WriteDB(_resultTable);
                    _resultTable.Rows.Clear();
                }
            }

        }
        private void SaveParse(IEnumerable<DepBank.TBL_RASP_GR> currentParseSet, char evaluationType, int rankOrder, float score)
        {
            foreach (var parse in currentParseSet)
            {
                DataRow row = _resultTable.NewRow();
                row["EvaluationSetType"] = evaluationType;
                row["SentenceID"] = parse.SentenceID;
                row["GRType"] = parse.GRType;
                row["H_Word"] = parse.H_Word;
                row["H_RPOS"] = parse.H_Lema_RPOS;
                if (parse.H_Lema_Location != null)
                {
                    row["H_Location"] = parse.H_Lema_Location;
                }
                else
                {
                    row["H_Location"] = DBNull.Value;
                }
                row["D_Word"] = parse.D_Word;
                row["D_RPOS"] = parse.D_Lema_RPOS;
                if (parse.D_Lema_Location != null)
                {
                    row["D_Location"] = parse.D_Lema_Location;
                }
                else
                {
                    row["D_Location"] = DBNull.Value;
                }
                row["SubType"] = parse.SubType;
                row["InitGR"] = parse.InitGR;
                row["ParseID"] = parse.ParseID;
                row["Rank"] = rankOrder;
                row["Score"] = score;
                _resultTable.Rows.Add(row);
            }
        }
        private void WriteDB(DataTable tbl_eval)
        {
            #region WriteDB

            using (SqlConnection con = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["TestBench.Properties.Settings.DepBankConnectionString"].ConnectionString))
            {

                if (con.State == ConnectionState.Closed)
                {
                    con.Open();
                }
                using (SqlBulkCopy bc = new SqlBulkCopy(con))
                {

                    bc.BulkCopyTimeout = 360;
                    bc.ColumnMappings.Add("EvaluationSetType", "EvaluationSetType");
                    bc.ColumnMappings.Add("SentenceID", "SentenceID");
                    bc.ColumnMappings.Add("GRType", "GRType");
                    bc.ColumnMappings.Add("H_Word", "H_Word");
                    bc.ColumnMappings.Add("H_RPOS", "H_RPOS");
                    bc.ColumnMappings.Add("H_Location", "H_Location");
                    bc.ColumnMappings.Add("D_Word", "D_Word");
                    bc.ColumnMappings.Add("D_RPOS", "D_RPOS");
                    bc.ColumnMappings.Add("D_Location", "D_Location");
                    bc.ColumnMappings.Add("SubType", "SubType");
                    bc.ColumnMappings.Add("InitGR", "InitGR");
                    bc.ColumnMappings.Add("ParseID", "ParseID");
                    bc.ColumnMappings.Add("Rank", "Rank");
                    bc.ColumnMappings.Add("Score", "Score");

                    bc.DestinationTableName = "TBL_Eval";
                    bc.WriteToServer(tbl_eval);
                    tbl_eval.Rows.Clear();
                    bc.Close();

                }

            }
            #endregion
        }

        private void btn_Test2_Click(object sender, EventArgs e)
        {
            using (DepBank_DBDataContext context = new DepBank_DBDataContext())
            {

                DepBank.TBL_GoldStandard_GR[] gs_gr = (from gs in context.TBL_GoldStandard_GRs select gs).ToArray();

                for (int i = 0; i < gs_gr.Length; i++)
                {
                    DepBank.TBL_GoldStandard_GR gr = gs_gr[i];

                    var mod = (from gs in context.TBL_GoldStandard_GRs where gs.GRID == gr.GRID select gs).Single();


                    bool isDepChage = false;
                    bool isHedChange = false;

                    if (gr.H_Word == "###hed")
                    {
                        mod.H_Lema = "###hed";
                        mod.H_RPOS = "###pos";
                        mod.H_Location = 0;
                        isHedChange = true;
                    }

                    if (gr.D_Word == "###dep")
                    {
                        mod.D_Lema = "###dep";
                        mod.D_RPOS = "###pos";
                        mod.D_Location = 0;
                        isDepChage = true;
                    }



                    if (isDepChage && isHedChange)
                    {
                        context.SubmitChanges();
                        continue;
                    }

                    if (!isHedChange)
                    {
                        DepBank.TBL_DepBank_Sen[] values = (from x in context.TBL_DepBank_Sens where x.EvaluationSetType == gr.EvaluationSetType.Value && x.SentenceID == gr.SentenceID.Value && x.Word == gr.H_Word select x).ToArray();


                        if (values.Length == 1)
                        {
                            DepBank.TBL_DepBank_Sen h_word = values[0];
                            mod.H_Lema = h_word.Lema;
                            mod.H_RPOS = h_word.POS;
                            mod.H_Location = h_word.Location;
                        }
                        else if (values.Length > 1)
                        {
                            bool isLemaSame = true;
                            bool isPOSSame = true;
                            foreach (var val in values)
                            {
                                if (values[0].Lema != val.Lema)
                                {
                                    isLemaSame = false;
                                }

                                if (values[0].POS != val.POS)
                                {
                                    isPOSSame = false;
                                }
                            }

                            if (isLemaSame)
                            {

                                mod.H_Lema = values[0].Lema;

                            }
                            if (isPOSSame)
                            {
                                mod.H_RPOS = values[0].POS;
                            }

                        }
                    }

                    if (!isDepChage)
                    {
                        DepBank.TBL_DepBank_Sen[] values = (from x in context.TBL_DepBank_Sens where x.EvaluationSetType == gr.EvaluationSetType && x.SentenceID == gr.SentenceID.Value && x.Word == gr.D_Word select x).ToArray();
                        if (values.Length == 1)
                        {
                            DepBank.TBL_DepBank_Sen d_word = values[0];
                            mod.D_Lema = d_word.Lema;
                            mod.D_RPOS = d_word.POS;
                            mod.D_Location = d_word.Location;
                        }
                        else if (values.Length > 1)
                        {
                            bool isLemaSame = true;
                            bool isPOSSame = true;
                            foreach (var val in values)
                            {
                                if (values[0].Lema != val.Lema)
                                {
                                    isLemaSame = false;
                                }

                                if (values[0].POS != val.POS)
                                {
                                    isPOSSame = false;
                                }

                            }

                            if (isLemaSame)
                            {
                                mod.D_Lema = values[0].Lema;
                            }
                            if (isPOSSame)
                            {
                                mod.D_RPOS = values[0].POS;
                            }

                        }
                    }

                    context.SubmitChanges();

                }

            }
        }

        private void btnFindCycles_Click(object sender, EventArgs e)
        {
            using (DepBank_DBDataContext context = new DepBank_DBDataContext()) {
                var eval_sen_set = (from x in context.TBL_Evals select new { E = x.EvaluationSetType, S = x.SentenceID }).Distinct();
                int i = 0;
                foreach (var eval_sen in eval_sen_set) {
                    var parseSet = from x in context.TBL_Evals where x.EvaluationSetType == eval_sen.E && x.SentenceID == eval_sen.S select x;
                    List<DepBank.TBL_Eval> cycleSet = new List<DepBank.TBL_Eval>();
                    foreach (var parse in parseSet) {
                        var current_cycles = from x in parseSet where x.D_Location == parse.H_Location && x.H_Location == parse.D_Location select x;
                        if (current_cycles.Count() > 0)
                        {
                            cycleSet.AddRange(current_cycles);
                        }
                    }
                    i++;
                    foreach (DepBank.TBL_Eval ev in cycleSet) {
                        DepBank.TBL_Cycle cycle = new DepBank.TBL_Cycle();
                        cycle.EvaluationSetType = ev.EvaluationSetType;
                        cycle.SentenceID = ev.SentenceID;
                        cycle.GRType = ev.GRType;
                        cycle.H_Location = ev.H_Location;
                        cycle.H_Lema = ev.H_Lema;
                        cycle.H_RPOS = ev.H_RPOS;
                        cycle.H_Word = ev.H_Word;
                        cycle.D_Location = ev.D_Location;
                        cycle.D_Lema = ev.D_Lema;
                        cycle.D_RPOS = ev.D_RPOS;
                        cycle.D_Word = ev.D_Word;
                        cycle.SubType = ev.SubType;
                        cycle.InitGR = ev.InitGR;
                        context.TBL_Cycles.InsertOnSubmit(cycle);
                    }
                    context.SubmitChanges();
                }
            }
        }

        private void btnBagOfGR_Click(object sender, EventArgs e)
        {
            using (SSD_DepBankDataContext context = new SSD_DepBankDataContext()) {
                context.CommandTimeout = 600;

                //context.ExecuteCommand("UPDATE TBL_BagOfWordGoldDiff SET ToBeRemoved='1'", new object[] { });

                var grset = from bw in context.TBL_BagOfWordGoldDiffs group bw by new { bw.EvaluationSetType, bw.SentenceID } into g select new { ID = g.Key, GRset = g };

                foreach (var set in grset)
                {
                    var oSet = set.GRset.OrderByDescending(i => i.Prob_2);
                    var roots = (from r in oSet where !(from dloc in oSet select dloc.D_Location).Contains(r.H_Location) select r).OrderByDescending(i => i.Prob_2);
                    foreach (var root in roots)
                    {
                        bool isRootCrash = (from r in roots where r.ToBeRemoved == false select r.D_Location).Contains(root.D_Location);
                        if (! isRootCrash)
                        {
                            root.ToBeRemoved = false;
                        }
                    }

                }
                context.SubmitChanges();

                foreach (var set in grset)
                {
                    var oSet = set.GRset.Where(i => i.ToBeRemoved == true).OrderByDescending(i => i.Prob_1);
                    for (int count = 1; count < 10; count++)
                    {
                        foreach (var nod in oSet)
                        {

                            var dlocs = from x in set.GRset.Where(i => i.ToBeRemoved == false) select x.D_Location;

                            bool isDepCrash = (dlocs).Contains(nod.D_Location);
                            if (!isDepCrash)
                            {
                                bool isHeadSlotAvailable = (dlocs).Contains(nod.H_Location);
                                if (isHeadSlotAvailable)
                                {
                                    nod.ToBeRemoved = false;
                                }
                            }

                        }
                    }

                }
                context.SubmitChanges();

               

            }
        }
    }



    public class ScoreSet
    {
        public float Score;
        public int ParseID;
    }
}
